package com.zhouyu;

import com.zhouyu.service.User;
import com.zhouyu.service.UserService;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@EnableTransactionManagement
@EnableAspectJAutoProxy
public class Test {

	public static void main(String[] args) {

		// 创建一个Spring容器
		//配置类解析流程 1 传入AppConfig.class配置类
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Test.class,AppConfig.class);
		

		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();
		applicationContext.close();

		/*AnnotationMetadata annotationMetadata = AnnotationMetadata.introspect(BeanObj3.class);
		MergedAnnotations annotations = annotationMetadata.getAnnotations();

		// 判断注解是否存在
		boolean present = annotations.isPresent(Component.class);
		// 获取注解的属性
		MergedAnnotation<Component> mergedAnnotation = annotations.get(Component.class);
		AnnotationAttributes annotationAttributes = mergedAnnotation.asAnnotationAttributes();*/

		/**
		 * SimpleAnnotationMetadataReadingVisitor与StandardAnnotationMetadata的区别与使用方法。由于这两个类使用起来步骤比较多，
		 * 文中又介绍了spring提供的两个工具类：AnnotationUtils与AnnotatedElementUtils，
		 * 如果需要处理属性覆盖，需要使用AnnotatedElementUtils，如果不需要，就使用AnnotationUtils。
		 *
		 */

//		UserService userService1 = new UserService();
//
//		for (Field field : userService1.getClass().getDeclaredFields()) {
//			if (field.isAnnotationPresent(Autowired.class)) {
//				field.set(userService1, ??);
//			}
//		}
//
//
//		for (Method method : userService1.getClass().getDeclaredMethods()) {
//			if (method.isAnnotationPresent(PostConstruct.class)) {
//				method.invoke(userService1, null);
//			}
//		}
//
//		if (userService1 instanceof InitializingBean) {
//			try {
//				((InitializingBean)userService1).afterPropertiesSet();
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}
//
//		ProxyFactory proxyFactory = new ProxyFactory();
//		proxyFactory.setTarget(userService1);
//		proxyFactory.addAdvice(new MethodInterceptor() {
//			@Nullable
//			@Override
//			public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
//				System.out.println("切面逻辑 before...");
//				Object result = invocation.proceed();
////				Object result = invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments());
//				System.out.println("切面逻辑 after...");
//				return result;
//			}
//		});
//		UserService userService2  = (UserService) proxyFactory.getProxy();
//		userService2.test();


	}
}







